iT邦幫忙

2023 iThome 鐵人賽

DAY 10
0
SideProject30

初探 Godot系列 第 10

[DAY 10] 物理效果 (_physics_process, StaticBody2D)

  • 分享至 

  • xImage
  •  

今日目標:建立一個具有物理特性的固定物件


▍事前準備

首先建立一個如 Day8 的 player 場景,不過先不要加上腳本

# 架構如下
|--CharacterBody2D
|   |--CollisionShape2D
|   |--Sprite2D
  • 介紹 StaticBody2D

    A 2D physics body that can't be moved by external forces. When moved manually, it doesn't affect other bodies in its path.

    A 2D physics body that can't be moved by external forces. When moved manually, it doesn't affect other bodies in its path.

      這個節點不會被外力影響或移動,若手動移動也不會影響到其他物體。
    

▍出發

現在我們要在 player 加上物理設定。

  • 附加腳本到 CharacterBody2D,樣板選擇 Object: Empty,會產生一個空的腳本:

    extends CharacterBody2D
    
  • 先宣告我們的重力,取得的位置在 專案 -> 專案設定 -> 一般 -> 物理 -> 2D -> Default Gravity

    var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
    
  • 接著新增物理迴圈 _physics_process

    func _physics_process(delta):
        # 待會新增物理邏輯位置
    
  • 在迴圈中新增判斷檢測物件是否在地面上,若否則更新角色的垂直速度。

        if not is_on_floor():
            velocity.y += gravity * delta
    

    The up_direction and floor_max_angle are used to determine whether a surface is "floor" or not.

    在說明中可以看到判斷地面的方式是 up_direction 及 floor_max_angle 這兩個屬性,up_direction 是一個朝上的向量,floor_max_angle 是最大能被判斷為地板的角度預設為 45度,超過 45度就不會被當作地板並持續觸發我們的判斷。

  • 最後呼叫 move_and_slide() 方法。

            move_and_slide()
    

    Moves the body based on velocity. If the body collides with another, it will slide along the other body (by default only on floor) rather than stop immediately. (...)

    這邊擷取說明的一部分,簡單看可以知道這個方法會根據 velocity 移動我們的物件並且會有慣性的滑動不會直接停止。

  • 完成我們的角色物理設定儲存場景(註:這次為了方便後續觀察有將 scale (屬性面板 -> Node2D -> Transform -> Scale)調小)

▍完整檔案 -1

extends CharacterBody2D

var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")

func _physics_process(delta):
	if not is_on_floor():
		velocity.y += gravity * delta
	move_and_slide()

  • 再來建立新場景作為主場景,先新增 Node 節點作為根節點,並將 Day2 的腳本直接附加在根節點上,讓我們點擊時產生我們剛剛做好的 player 場景。

▍完整檔案 -2(如 Day2

extends Node

@export var player_scene:PackedScene

# Called when the node enters the scene tree for the first time.
func _ready():
	pass

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
    # 這裡更改為 just pressed 避免一次點擊觸發多次的情況發生
	if Input.is_action_just_pressed("left_click"):
		spawn()
	
func spawn():
	var godot = player_scene.instantiate()
	godot.position = get_viewport().get_mouse_position()
	add_child(godot)

現在播放就可以看到物件會持續下落。

  • 現在我們在根節點下建立一個 StaticBody2D 作為我們測試用的固定物理物件可以產生碰撞,在節點下加入 CollisionPolygon2D 讓我們能繪製物件的碰撞形狀,繪製方式如昨日 Polygon2D 方法,繪製完成後為了方便觀察我們一樣再加入 Polygon2D 加上顏色。
# 結構如下
|--StaticBody2D
|   |--CollisionPolygon2D # 在 2D 場景中新增頂點
|   |--Polygon2D # 在 2D 場景中新增頂點

https://ithelp.ithome.com.tw/upload/images/20230925/20162875qFg716HCjz.png

▍執行

Yes

▍完成

:)


上一篇
[DAY 9] 接觸 Part.2 (Area2D, Polygon2D)
下一篇
[DAY 11] 專案設定 (視窗, 大小, 伸縮)
系列文
初探 Godot30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言